package mware_lib;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import mware_lib.tcp.Client;

public class LocalNS extends NameService { //<<< Interface implementieren!

    List<ISkeleton> skeletons = new ArrayList<>();
    int portGlobalNS;
    String ipGlobalNS;
    Client client = null;
    int brokerPort;
    Map<String, ObjectRef> cache = new HashMap<>();

    public LocalNS(String ip, int port, int brokerPort) {
        this.ipGlobalNS = ip;
        this.portGlobalNS = port;
        this.brokerPort = brokerPort;
    }

    @Override
    public void rebind(Object o, String s) {
        try {
          System.out.println("LocalNS.rebind(" + o + "," + s + ")");
            client = new Client(ipGlobalNS, portGlobalNS);
        } catch (IOException ex) {
            return;
        }

        
        try {
            ISkeleton skeletonOfObject = ((IProxy) o).getSkeleton();
            //ListIndex setzen
            skeletons.add(skeletonOfObject);
            ObjectRef objectRef = new ObjectRef("127.0.0.1", brokerPort, skeletons.size() - 1);

            String objectString = "1/" + objectRef.stringRep() + "/" + s;

            client.writeObject(objectString);
            client.readObject();
        } catch (IOException ex) {
            throw new RuntimeException("Verbindung zum Nameserver wurde während einer Anfrage unterbrochen!");
        } finally {
          try {
            client.close();
          } catch (IOException ex) {}
        }
    }
    

    @Override
    public Object resolve(String name) {
      if (!cache.containsKey(name))
        cache.put(name, directResolve(name));
      return cache.get(name);
    }
    
    public ObjectRef directResolve(String name) {
      System.out.println("LocalNS.resolve(" + name + ")");
        String result ="";
        try {
            try {
                client = new Client(ipGlobalNS, portGlobalNS);
            } catch (IOException ex) {
                throw new RuntimeException("client could not initialite (resolve-Method)");
            }

            client.writeObject("0/" + name + "/" + name);//hier
            result = (String) client.readObject();
        } catch (IOException ex) {
            Logger.getLogger(LocalNS.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
          try {
            client.close();
          } catch (IOException ex) {
            Logger.getLogger(LocalNS.class.getName()).log(Level.SEVERE, null, ex);
          }
        }
        if (result != "0") {
            String[] resolvedArr = result.split("!");
            String[] formattedResolve = resolvedArr[1].split(":");
            return new ObjectRef(formattedResolve[0], Integer.parseInt(formattedResolve[1]), Integer.parseInt(formattedResolve[2]));
        }
        else
        {
            throw new RuntimeException("resolveFormat was wrong");
        }
    }

    @Override
    public Serializable invokeLocalMethod(ObjectRef object, String method, Serializable[] params) {
        return skeletons.get(object.listIndex).invokeMethod(method, params);
    }

    @Override
    public void shutdown() {
      //Es gibt keine Threads, die beendet werden müssten
    }
}
